/******************************************************************************
 * Copyright (C) 2015  671643387@qq.com
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 *****************************************************************************/

#ifndef SHARED_EXCEPTION_H_
#define SHARED_EXCEPTION_H_

#include <cstddef>
#include <string>
#include <exception>
#include <iostream>

class Exception : public std::exception
{
public:
	Exception(void);
	explicit Exception(int code);
	Exception(const std::string& msg, int code);
	~Exception(void) throw ();

	int code(void) const;
	const char* message(void) const;
	const char* what(void) const throw ();

private:
	int code_;
	std::string msg_;
};

inline int Exception::code(void) const
{
	return code_;
}

inline const char* Exception::message(void) const
{
	return msg_.c_str();
}

inline const char* Exception::what(void) const throw ()
{
	return msg_.c_str();
}

//-------------------------------------------------------------------------
#define DECLARE_EXCEPTION_CODE(CLS, BASE, CODE)                          \
	class CLS : public BASE                                              \
	{                                                                    \
	public:                                                              \
		CLS(int code = CODE);                                            \
		CLS(const std::string& msg, int code = CODE);                    \
		~CLS() throw ();                                                 \
		CLS& operator = (const CLS& exc);                                \
		const char* name() const;                                        \
		const char* className() const;                                   \
	};

#define DECLARE_EXCEPTION(CLS, BASE)                                     \
	DECLARE_EXCEPTION_CODE(CLS, BASE, 0)

#define IMPLEMENT_EXCEPTION(CLS, BASE, NAME)                             \
	CLS::CLS(int code) : BASE(code)                                      \
	{                                                                    \
	}                                                                    \
	CLS::CLS(const std::string& msg, int code) : BASE(msg, code)         \
	{                                                                    \
	}                                                                    \
	CLS::~CLS() throw ()                                                 \
	{                                                                    \
	}                                                                    \
	CLS& CLS::operator = (const CLS& exc)                                \
	{                                                                    \
		BASE::operator = (exc);                                          \
		return *this;                                                    \
	}                                                                    \
	const char* CLS::name() const                                        \
	{                                                                    \
		return NAME;                                                     \
	}                                                                    \
	const char* CLS::className() const                                   \
	{                                                                    \
		return typeid(*this).name();                                     \
	}

DECLARE_EXCEPTION(LogicException, Exception)
DECLARE_EXCEPTION(AssertionViolationException, LogicException)
DECLARE_EXCEPTION(NullPointerException, LogicException)
DECLARE_EXCEPTION(NullValueException, LogicException)
DECLARE_EXCEPTION(BugcheckException, LogicException)
DECLARE_EXCEPTION(InvalidArgumentException, LogicException)
DECLARE_EXCEPTION(NotImplementedException, LogicException)
DECLARE_EXCEPTION(RangeException, LogicException)
DECLARE_EXCEPTION(IllegalStateException, LogicException)
DECLARE_EXCEPTION(InvalidAccessException, LogicException)
DECLARE_EXCEPTION(SignalException, LogicException)
DECLARE_EXCEPTION(UnhandledException, LogicException)

DECLARE_EXCEPTION(RuntimeException, Exception)
DECLARE_EXCEPTION(NotFoundException, RuntimeException)
DECLARE_EXCEPTION(ExistsException, RuntimeException)
DECLARE_EXCEPTION(TimeoutException, RuntimeException)
DECLARE_EXCEPTION(SystemException, RuntimeException)

#endif /* SHARED_EXCEPTION_H_ */
